/******************************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Ltd.                       */
/*                                                                            */
/*  NAME      = db2_cmd_obj.c                                                 */
/*  NOTE      = TDS 请求解析                                                  */
/*  DATE      = 2015/03/19 by zhengxd                                         */
/******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

#include "db2_param.h"
#include "db2_froca.h"
#include "db2_cmd_obj.h"

/*******************************************************************************
*  FUNC     :  跳过OBJECT
*  ARGS     :  p_st_fragment(分片包信息)
*           :  i_whole_flg(packet完整标识)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int db2_skip_cmd_obj(L7_fragment_db2 *p_st_fragment, int i_whole_flg)
{
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;
    unsigned int ui_obj_len = p_st_fragment->ui_left_obj_len;
    unsigned int ui_remaining_len = bytebuff_remaining(p_st_data);

    /* 剩余长度不足 */
    if (ui_remaining_len < ui_obj_len)
    {
        if (i_whole_flg == DB2_TRUE)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        else
        {
            /* 设置要跳过的长度 */
            bytebuff_set_skip(p_st_data, ui_obj_len - ui_remaining_len);
            return APM_L7_ANALYZE_TODO;
        }
    }

    /* 跳过当前parameter */
    bytebuff_skip(p_st_data, ui_obj_len);
    p_st_fragment->i_obj_cp = DRDA_CP_NULL;
    p_st_fragment->ui_left_obj_len = 0;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  取得SQLSTT
*  ARGS     :  p_st_fragment(分片包信息)
*           :  i_whole_flg(packet完整标识)
*           :  pp_sql(取得的sql)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int db2_get_sqlstt(L7_fragment_db2 *p_st_fragment
                  , int i_whole_flg, char **pp_sql)
{
    int i_ret = FR_SUCC;
    unsigned int ui_len = 0;
    uint8_t u8_word = 0;
    uint32_t u32_len = 0;
    char *p_data = NULL;
    char *p_data_tmp = NULL;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;
    unsigned int ui_obj_len = p_st_fragment->ui_left_obj_len;
    unsigned char arr_tmp[3] = {0};

    /* 剩余长度不足 */
    if (ui_obj_len > (unsigned int)bytebuff_remaining(p_st_data))
    {
        if (i_whole_flg == DB2_TRUE)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        else
        {
            return APM_L7_ANALYZE_TODO;
        }
    }

    /* 申请一块存放源数据的内存 */
    p_data = (char *)frmalloc(ui_obj_len + 1);
    if (p_data == NULL)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    p_data_tmp = p_data;

    /* 取得源数据块 */
    ui_len = ui_obj_len;
    while (ui_len)
    {
        i_ret = bytebuff_get_char(p_st_data, &u8_word);
        if (i_ret != FR_SUCC)
        {
            frfree(p_data);
            return APM_L7_ANALYZE_FAIL;
        }
        ui_len--;

        switch (u8_word)
        {
            /* 真实数据开始 */
            case 0x00:
                if (ui_len < 4)
                {
                    frfree(p_data);
                    return APM_L7_ANALYZE_FAIL;
                }

                /* 取得该段数据的长度 */
                i_ret = bytebuff_get_int(p_st_data, 4, &u32_len, BYTE_BIG_ENDIAN);
                if (i_ret != FR_SUCC || u32_len > ui_len - 4)
                {
                    frfree(p_data);
                    return APM_L7_ANALYZE_FAIL;
                }

                /* 取得该段数据的值 */
                i_ret = bytebuff_get_bytes(p_st_data, p_data_tmp, u32_len);
                if (i_ret != FR_SUCC)
                {
                    frfree(p_data);
                    return APM_L7_ANALYZE_FAIL;
                }
                p_data_tmp[u32_len] = '\0';
                p_data_tmp += u32_len;
                ui_len -= 4 + u32_len;

                if (ui_len == 2 + 1)
                {
                    i_ret = bytebuff_peek_bytes(p_st_data, arr_tmp, 3);
                    if (i_ret != FR_SUCC)
                    {
                        frfree(p_data);
                        return APM_L7_ANALYZE_FAIL;
                    }
                    if (arr_tmp[2] == 0xff)
                    {
                        memcpy(p_data_tmp, arr_tmp, 2);
                        p_data_tmp += 2;
                        ui_len -= 2;
                        *p_data_tmp = '\0';
                        bytebuff_skip(p_st_data, 2);
                    }
                }
                break;

            /* 真实数据结束 */
            case 0xFF:
                break;

            default:
                frfree(p_data);
                return APM_L7_ANALYZE_FAIL;
        }
    }

    /* 如果pp_sql有值需要将两个合并,以[;]分开 */
    if (*pp_sql)
    {
        ui_len = strlen(*pp_sql) + ui_obj_len + 1 + 1;
        p_data_tmp = (char *)frmalloc(ui_len);
        if (p_data_tmp == NULL)
        {
            frfree(p_data);
            return APM_L7_ANALYZE_FAIL;
        }
        snprintf(p_data_tmp, ui_len, "%s;%s", *pp_sql, p_data);
        frfree(*pp_sql);
        frfree(p_data);
        *pp_sql = p_data_tmp;
    }
    else
    {
        *pp_sql = p_data;
    }

    /* 初始化object信息 */
    p_st_fragment->i_obj_cp = DRDA_CP_NULL;
    p_st_fragment->ui_left_obj_len = 0;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析SQLDTA
*  ARGS     :  p_st_fragment(分片包信息)
*           :  i_whole_flg(packet完整标识)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int db2_parse_sqldta(L7session_db2_private *p_st_private, int i_whole_flg)
{
    int i_ret = FR_SUCC;
    int i_typdef = 0;
    int i_param_cp = 0;
    unsigned int ui_param_bd_len = 0;
    L7_req_db2 *p_st_req = p_st_private->p_st_req;
    L7session_db2 *p_st_sess = p_st_private->p_st_sess;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /* 取得type define */
    if (p_st_req->i_typdef != DRDA_TYPDEF_UNKNOW)
    {
        i_typdef = p_st_req->i_typdef;
    }
    else
    {
        i_typdef = p_st_sess->i_cli_typdef;
    }

    /* 解析参数 */
    while (p_st_fragment->ui_left_obj_len)
    {
        i_ret = db2_get_param_hd_info(p_st_fragment, i_whole_flg
                                     , &p_st_fragment->ui_left_obj_len
                                     , &i_param_cp, &ui_param_bd_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("SQLDTA: need more data or get parameter info failed!\n");
            return i_ret;
        }

        switch (i_param_cp)
        {
            /* 暂时不处理FDOEXT/FDOOFF,直接跳过 */
            case DRDA_CP_FDOEXT:
            case DRDA_CP_FDOOFF:
                frdbg("Please attetion!!!\n");
                i_ret = db2_skip_param(p_st_data, ui_param_bd_len, i_whole_flg
                                       , &p_st_fragment->ui_left_obj_len);
                break;

            /* 取得数据描述 */
            case DRDA_CP_FDODSC:
                i_ret = db2_get_fdodsc(p_st_data, i_whole_flg, ui_param_bd_len
                                      , &p_st_req->st_metadata
                                      , &p_st_fragment->ui_left_obj_len);
                break;

            /* 取得BIND参数 */
            case DRDA_CP_FDODTA:
                i_ret = db2_parse_sqldata(p_st_data, i_whole_flg, i_typdef
                                         , ui_param_bd_len
                                         , &p_st_req->st_metadata
                                         , &p_st_req->st_bind
                                         , &p_st_fragment->ui_left_obj_len);
                break;

            default:
                frdbg("SQLDTA: Unknow parameter!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 数据不足或者解析出错 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("SQLDTA: need more data or parse failed!\n");
            return i_ret;
        }
        /* 为取下一个参数做初始化准备 */
        p_st_fragment->i_param_cp = DRDA_CP_NULL;
    }

    /* 初始化object信息 */
    p_st_fragment->i_obj_cp = DRDA_CP_NULL;
    return APM_L7_ANALYZE_SUCC;
}
